package com.ldf.media.websocket;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class WebRTCWebSocketHandler extends TextWebSocketHandler {
    
    // 存储所有连接的WebSocket会话
    private static final ConcurrentHashMap<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
    
    // 存储用户之间的连接关系
    private static final ConcurrentHashMap<String, String> userConnections = new ConcurrentHashMap<>();
    
    private final ObjectMapper objectMapper = new ObjectMapper();
    
    /**
     * 建立连接时触发
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String userId = extractUserIdFromHandshake(session);
        if (userId == null) {
            log.warn("用户未提供ID，拒绝连接");
            session.close(CloseStatus.POLICY_VIOLATION);
            return;
        }
        sessions.put(userId, session);
        log.info("用户 {} 连接到WebSocket服务器", userId);
        
        // 通知其他用户有新用户加入
        broadcastToOthers(session, objectMapper.writeValueAsString(new Message("joined", userId)));
    }

    /**
     * 从连接参数中提取用户ID
     */
    private String extractUserIdFromHandshake(WebSocketSession session) {
        // 示例：假设客户端连接时使用 ws://...?userId=xxx
        return session.getUri().getQuery().split("=")[1];
    }
    
    /**
     * 收到消息时触发
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        log.debug("收到消息: {}", payload);
        
        try {
            JsonNode jsonNode = objectMapper.readTree(payload);
            String type = jsonNode.get("type").asText();
            String toUserId = jsonNode.has("to") ? jsonNode.get("to").asText() : null;
            
            // 根据消息类型处理
            switch (type) {
                case "offer":
                case "answer":
                case "candidate":
                case "hangup":
                case "ready":
                    // 转发消息给指定用户
                    if (toUserId != null && sessions.containsKey(toUserId)) {
                        WebSocketSession targetSession = sessions.get(toUserId);
                        if (targetSession.isOpen()) {
                            targetSession.sendMessage(new TextMessage(payload));
                        }
                    }
                    break;
                    
                default:
                    log.warn("未知消息类型: {}", type);
                    break;
            }
        } catch (Exception e) {
            log.error("处理WebSocket消息时出错", e);
        }
    }
    
    /**
     * 连接关闭时触发
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        String userId = extractUserIdFromHandshake(session);
        sessions.remove(userId);
        log.info("用户 {} 断开WebSocket连接，状态: {}", userId, status);
        
        // 移除用户连接关系
        userConnections.remove(userId);
        userConnections.values().removeIf(id -> id.equals(userId));
        
        // 通知其他用户该用户已离线
        try {
            broadcastToOthers(session, objectMapper.writeValueAsString(new Message("left", userId)));
        } catch (Exception e) {
            log.error("广播用户离线消息失败", e);
        }
    }
    
    /**
     * 传输错误时触发
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.error("WebSocket传输错误，用户ID: {}", session.getId(), exception);
        session.close(CloseStatus.SERVER_ERROR);
        sessions.remove(session.getId());
    }
    
    /**
     * 向除了指定用户外的所有用户广播消息
     */
    private void broadcastToOthers(WebSocketSession senderSession, String message) throws Exception {
        for (WebSocketSession session : sessions.values()) {
            if (!session.getId().equals(senderSession.getId()) && session.isOpen()) {
                session.sendMessage(new TextMessage(message));
            }
        }
    }
    
    /**
     * 消息封装类
     */
    private static class Message {
        public String type;
        public String userId;
        public long timestamp;
        
        public Message(String type, String userId) {
            this.type = type;
            this.userId = userId;
            this.timestamp = System.currentTimeMillis();
        }
    }
}